import Module from 'module'
import { sep, resolve } from "path"
import { existsSync } from "fs"
import { parseSync } from "@swc/core";

export const createRequire = Module.createRequire || Module.createRequireFromPath;

export const parseImportModule = function (code: string, libList: []) {
  const ast = parseSync(code, {
    syntax: "typescript",
    tsx: true
  }).body;

  const importMaps = {};
  ast.forEach((astNode: any) => {
    if (astNode.type !== 'ImportDeclaration') return;

    const libraryName = astNode.source.value;
    const matchLib = libList.find((lib: any) => lib.libraryName === libraryName);

    if (!matchLib) return;
    if (astNode.specifiers.length === 0) return;

    astNode.specifiers.forEach((item: any) => {
      if (item.type === "ImportNamespaceSpecifier") {
        console.warn(`Can't transform code`);
        return;
      }

      let name: string;
      if (item.type === "ImportDefaultSpecifier") {
        name = "default";
      } else if (item.local.type === "Identifier") {
        name = item.local.value
      } else if (item.local.name) {
        name = item.local.name
      }

      if (importMaps[libraryName]) {
        importMaps[libraryName].push(name);
      } else {
        importMaps[libraryName] = [name];
      }
    });
  });

  return { importMaps };
};

export const codeIncludesLibraryName = (code: string, libList = []) => {
  return !libList.every(({ libraryName }) => {
    return !new RegExp(`('${libraryName}')|("${libraryName}")`).test(code);
  })
};

export const stylePathHandler = (stylePath: string, ignoreStylePathNotFound = true) => {
  let str = ''
  if (isString(stylePath) && stylePath) {
    str += stylePathNotFoundHandler(stylePath, ignoreStylePathNotFound)
  } else if (Array.isArray(stylePath)) {
    stylePath.forEach((item) => {
      str += stylePathNotFoundHandler(item, ignoreStylePathNotFound)
    })
  }
  return str
}

export const stylePathNotFoundHandler = (stylePath: string, ignoreStylePathNotFound: boolean) => {
  if (ignoreStylePathNotFound) {
    let stylePathExists = true
    try {
      createRequire(process.cwd() + sep).resolve(stylePath)
    } catch (error) {
      stylePathExists = error?.code !== 'MODULE_NOT_FOUND'
    }

    if (!stylePathExists) {
      const fullStylePath = resolve(process.cwd(), 'node_modules', stylePath)
      const lastPath = fullStylePath.split('/').pop()
      if (!lastPath?.includes('.')) {
        const possibleEndWithsPaths = [
          '/index.js',
          '/index.mjs',
          '.js',
          '.mjs'
        ];
        if (possibleEndWithsPaths.some(p => existsSync(fullStylePath + p))) {
          stylePathExists = true
        }
      }
    }

    if (stylePathExists) {
      return `import '${stylePath}';`
    } else {
      console.warn(`${stylePath} is not found!`)
      return ''
    }
  }
  return `import '${stylePath}';`
}

export const isString = (obj: any) => (typeof obj === 'string')
export const isFunction = (x: any) => Object.prototype.toString.call(x) == '[object Function]'
export const isBool = (obj: any) => (typeof obj === 'boolean')